<?php
/*
* 系统菜单模型
* lsj 2010-11-28
*/

if(!defined('APP_HOME')) exit('Access Denied');

class menuMod extends lib_model
{
	protected $tbl = 'sys_menus';#当前模型操作的主表
	protected $cacheFile = '';#缓存文件路径
	protected $cacheMenu = array();#缓存起来的菜单数组
	protected $menuTree = array();#菜单树
	protected $deep = 0;#菜单的深度
	

	
	/**
	 * 初始化
	 */
	public function _init()
	{
		$this->cacheFile = CACHE_MANAGE . DS . 'menu.php';#缓存文件路径
		return true;
	}

	/**
	 * 从控制器名与动作名取菜单ID
	 * $ctrl: 控制器名
	 * $act: 动作名
	 */
	public function getId($ctrl, $act)
	{
		$menu = array();
		$this->readCacheMenu();
		if($this->cacheMenu){
			foreach($this->cacheMenu as $key=>$val){
				if($val['ctrl'] == $ctrl && $val['act'] == $act) $menu[] = $val['id'];
			}
		}
		return $menu;
	}
	
	/**
	 * 取出ID对应菜单类型
	 * $id: 菜单ID
	 */
	public function getType($id)
	{
		if(!$id) return false;
		$this->readCacheMenu();
		
		if(isset($this->cacheMenu[$id])) return $this->cacheMenu[$id]['mtype'];
		return null;
	}

	/**
	 * 取出ID对应菜单信息， 为0则为所有菜单
	 * $id: 菜单ID
	 */
	public function getInfo($id = 0)
	{
		$this->readCacheMenu();
		if(!$id) return $this->cacheMenu;
		if(isset($this->cacheMenu[$id])) return $this->cacheMenu[$id];
		return array();
	}

	/**
	 * 取出ID对应菜单的父ID
	 * $id: 菜单ID
	 */
	public function getFid($id)
	{
		if(!$id) return false;
		$this->readCacheMenu();
		
		if(isset($this->cacheMenu[$id])) return $this->cacheMenu[$id]['fid'];
		return null;
	}
	
	/**
	 * 取出ID对应的所有父级信息
	 * $id: 菜单ID
	 */
	public function getFather($id, $fathers = array())
	{
		if($id == 0) return $fathers;

		$this->readCacheMenu();
		if($this->cacheMenu){
			foreach($this->cacheMenu as $key=>$val){
				if($key == $id){
					array_unshift($fathers, $val);
					$fat = $this->getFather($val['fid'], $fathers);
				}
			}
		}
		
		return $fat;
	}

	/**
	 * 取出ID们对应的菜单树
	 * $idArr: 多个菜单ID，当为0时即为所有菜单的ID
	 */
	public function getTree($idArr = 0)
	{
		$this->readCacheMenu();
		$menu = array();
		if($this->cacheMenu){
			foreach($this->cacheMenu as $key=>$val){
				if(0 === $idArr || in_array($key, $idArr)) $menu[$val['fid']][$val['id']] = $val;
			}
		}
		return $menu;
	}

	/**
	 * 取出公共（须登录）菜单
	 */
	public function getPublic()
	{
        $this->readCacheMenu();
        $menu = array();
		if($this->cacheMenu){
            foreach($this->cacheMenu as $key=>$val){
				if($val['mtype'] == 'ALLIN') $menu[$val['id']] = $val;
			}
		}
		return $menu;
	}

    /**
     * 取出公共（勿登录）菜单
	 */
	public function getOpen()
	{
		$this->readCacheMenu();
        $menu = array();
		if($this->cacheMenu){
            foreach($this->cacheMenu as $key=>$val){
				if($val['mtype'] == 'ALLOUT') $menu[$val['id']] = $val;
			}
		}
		return $menu;
	}
	
	/**
	 * 通过菜单的类型，判断出是否属于管理员权限范围内的
	 */
	public function isAdmin($id)
	{
		$this->readCacheMenu();
		if($this->cacheMenu[$id]['mtype'] === 'ALLOUT' || $this->cacheMenu[$id]['mtype'] === 'ALLIN' || $this->cacheMenu[$id]['mtype'] === 'SEE') return true;
		return false;
	}

	/**
	 * 通过菜单的类型，判断出是否属于开放菜单
	 */
	public function isOpen($id)
	{
		$this->readCacheMenu();
		if($this->cacheMenu[$id]['mtype'] === 'ALLOUT') return true;
		return false;
	}
	
	/**
	 * 通过菜单的类型，判断出是否为隐藏属性
	 */
	public function isHide($id)
	{
		$this->readCacheMenu();
		if($this->cacheMenu[$id]['ishide'] == 1) return true;
		return false;
	}
	/**
	 * 将一个平级数组格式化出一个父子关系数组
	 * 返回数组
	 */
	 public function formatFather($res)
	 {
	 	$result = array();
	 	if(is_array($res)){
	 		foreach($res as $key=>$val){
	 			$result[$val['fid']][] = $val;
	 		}
	 	}
	 	return $result;
	 }
	
	/**
	 * 从父子关系数组中格式化出一个树
	 * 返回数组: ['order']:堆叠顺序  ['deep']:所处深度  ['menu']:菜单各项信息
	 */
	public function formatTree($res, $k=0)
	{
		if($this->deep > 10) return $this->menuTree;
		$deep = $this->deep;
		if(isset($res[$k])) {		
			$this->deep++;
			foreach($res[$k] as $key=>$val){
					$this->menuTree['order'][] = $val['id'];
					$this->menuTree['deep'][] = $this->deep;
					$this->menuTree['menu'][$val['id']] = $val;
					$this->formatTree($res, $val['id']);
			}
			$this->deep--;
		}else{
			$this->deep = $deep;
		}
		return $this->menuTree;
	}

	/*
	#写菜单数组到缓存文件
	*/
	public function writeCacheMenu()
	{
		#取出数据库中所有菜单的信息
		$result = $this->getMenu();

		$menu = array();
		if($result){
			foreach($result as $key=>$val){
				$menu[$val['id']] = $val;
			}
		}

		$LN = "\r\n";
		$menuStr = '<?php'.$LN;
		$menuStr .= '/*'.$LN;
		$menuStr .= '*系统菜单缓存'.$LN;
		$menuStr .= '*/'.$LN;
		$menuStr .= "if(!defined('APP_HOME')) exit('Access Denied');".$LN;
		$menuStr .= 'return ' . var_export($menu, true) . $LN;
		$menuStr .= '?>';
		if(file_put_contents($this->cacheFile, $menuStr)) return true;
		return false;
	}

	/*
	#读缓存起来的菜单数组
	*/
	public function readCacheMenu()
	{
		if(!file_exists($this->cacheFile)){
			$this->writeCacheMenu();
		}
		if(empty($this->cacheMenu)){
			$this->cacheMenu = require $this->cacheFile;
		}
		return $this->cacheMenu;
	}

	/*
	 * 从数据库获取菜单
	 */
	public function getMenu($id = 0, $sel = '*')
	{
		if(0 !== $id){
			if(is_array($id)) $id = join(',', $id);
			else $this->setLimit(1);
			$this->setId($id);
		}
		return $this->setOrderBy('weight', 'DESC')->select($sel);
	}

	/*
	 * 从数据库添加菜单
	 */
	public function addMenu($menu)
	{
		if($this->insert($menu)){
			if($this->writeCacheMenu()) return true;#更新缓存成功
			return -1;#更新缓存失败
		}
		return false;
	}

	/*
	 * 从数据库修改菜单
	 */
	public function editMenu($menu, $id = 0)
	{
		if($id) $this->setId($id);
		elseif(!empty($menu['id'])) $this->setId($menu['id']);
		if(isset($menu['id'])) unset($menu['id']);

		if($this->update($menu)){
			if($this->writeCacheMenu()) return true;#更新缓存成功
			return -1;#更新缓存失败
		}
		return false;
	}

	/*
	 * 从数据库删除菜单
	 */
	public function delMenu($id)
	{
		if($this->setId($id)->delete()){
			if($this->writeCacheMenu()) return true;#更新缓存成功
			return -1;#更新缓存失败
		}
		return false;
	}
	
	/*
	 * 获取所有控制器名称，并标识出菜单中已采用的数目
	 */
	public function getCtrls()
	{
		$dir = CTRL_ROOT;
		$ctrlsAll = array();#未添加到菜单表的控制器名
		$ctrls = array();#已添加到菜单表的控制器名
		$ctrlsYes = array();#已添加到菜单表的控制器名
		
		$ctrls = $this->setGroupBy('ctrl')->setWhere('ctrl', '', 'no')->getMenu(0, 'ctrl as name, count(*) as num');
    	if($ctrls){
    		foreach($ctrls as $key=>$val){
    			$ctrlsYes[$val['name']] = $val['num'];
    		}
    	}
    	
		if(is_dir($dir)){
		    if ($dh = opendir($dir)){		    	
		    	$i = 0;
		        while (($file = readdir($dh)) !== false){
		        	if($file == '.' || $file == '..' || substr($file, 0, 1) == '.') continue;
		        	$file = str_replace('Ctrl.php', '', $file);
		        	$ctrlsAll[$i]['name'] = $file;
		        	$ctrlsAll[$i]['num'] = 0;
		        	if(isset($ctrlsYes[$file]) && $ctrlsYes[$file] > 0) $ctrlsAll[$i]['num'] = $ctrlsYes[$file];
		        	$i++;
		        }
		        closedir($dh);
		    }
		}
		return $ctrlsAll;
	}
	
	/*
	 * 获取指家控制器内的动作名称
	 */
	public function getActs($ctrl)
	{
		$ctrl .= 'Ctrl';
		$acts = array();
		$ts = get_class_methods($ctrl);
		if($ts){
			$pts = get_class_methods(get_parent_class($ctrl));
			$ts = array_diff($ts, $pts);
			foreach($ts as $index=>$one){
				if(substr($one, -3) == 'Act') $acts[] = substr($one, 0, -3);
			}
		}
		
		return $acts;
	}
	
	/*
	 * 获取mtype的值
	 */
	public function getMtypes()
	{
		#也可以从数据库取，如：SHOW COLUMNS FROM sys_menus LIKE 'mtype'，不过需要处理下
		$mtypes = array(
				'SEE'=>'查看',
				'ADD'=>'添加',
				'EDIT'=>'编辑',
				'DEL'=>'删除',
				'ALLIN'=>'公共(须登录)',
				'ALLOUT'=>'公共(勿登录)',
				'OTHER'=>'其它',
			);
			
		return $mtypes;
	}
	
	/*
	 * 对菜单各字段的过滤， 用于过滤客户端提交来的数据
	 * 只对字段类型做处理，对长度不做处理，请在控制器做长度的处理
	 */
	public function filterItem($item)
	{
		if(empty($item)) return array();
		
		if(isset($item['id'])) $item['id'] = abs(intval($item['id']));
		if(isset($item['fid'])) $item['fid'] = abs(intval($item['fid']));
		if(isset($item['name'])) $item['name'] = trim($item['name']);
		if(isset($item['ctrl'])) $item['ctrl'] = filterHtml(trim($item['ctrl']));
		if(isset($item['act'])) $item['act'] = filterHtml(trim($item['act']));
		if(isset($item['isindex'])) $item['isindex'] = abs(intval($item['isindex']));
		if(isset($item['ishide'])) $item['ishide'] = abs(intval($item['ishide']));
		if(isset($item['mtype'])) $item['mtype'] = filterHtml(trim($item['mtype']));
		if(isset($item['weight'])) $item['weight'] = abs(intval($item['weight']));
		if(isset($item['notes'])) $item['notes'] = filterHtml(trim($item['notes']));
		
		return $item;
	}

	##############################################

	/*
	#设置菜单ID
	*/
	public function setId($d, $c = 'is')
	{
		return $this->setWhere('id', $d, $c);
	}

	/*
	#设置菜单FID
	*/
	public function setFid($d, $c = 'is')
	{
		return $this->setWhere('fid', $d, $c);
	}

	/*
	#设置菜单NAME
	*/
	public function setName($d, $c = 'is')
	{
		return $this->setWhere('name', $d, $c);
	}

	/*
	#设置菜单CTRL
	*/
	public function setCtrl($d, $c = 'is')
	{
		return $this->setWhere('ctrl', $d, $c);
	}

	/*
	#设置菜单ACT
	*/
	public function setAct($d, $c = 'is')
	{
		return $this->setWhere('act', $d, $c);
	}

	/*
	#设置菜单MTYPE
	*/
	public function setMtype($d, $c = 'is')
	{
		return $this->setWhere('mtype', $d, $c);
	}

	/*
	#设置菜单ISINDEX
	#$d: 1&0
	*/
	public function setIsindex($d)
	{
		return $this->setWhere('isindex', $d);
	}

	/*
	#设置菜单ISHIDE
	#$d: 1&0
	*/
	public function setIshide($d)
	{
		return $this->setWhere('ishide', $d);
	}

	/*
	#设置菜单WEIGHT
	*/
	public function setWeight($d, $c = 'is')
	{
		return $this->setWhere('weight', $d, $c);
	}



}




